
import random
import re
from datetime import datetime

from flask import request, abort, current_app, make_response, jsonify, session
from info import redis_store, constants, db
from info.libs.yuntongxun.sms import CCP
from info.models import User
from info.utils.response_code import RET
from . import passport_blu
from info.utils.captcha.captcha import captcha


@passport_blu.route("/image_code")
def get_image_code():
    """获取图片验证码"""
    # 1、获取image_code后加密参数
    image_code_id = request.args.get('imageCodeId', None)
    # 2、判断是否有值
    if not image_code_id:
        return abort(500)
    # 3、生成验证码 使用captcha工具生成
    name, text, image = captcha.generate_captcha()
    print(text)
    # 4、将image_code_id参数及验证码信息存储到redis中 并设置过期时间
    try:
        redis_store.set('image_code_id_' + image_code_id, text, ex=constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as a:
        # 将报错信息写入日志中
        current_app.logger.error(a)
        abort(500)
    # 5、返回验证码图片
    response = make_response(image)
    # 设置返回验证码格式为 image/jpg
    response.headers['Content-Type'] = 'image/jpg'
    return response


@passport_blu.route('/sms_code', methods=['POST'])
def send_sms_code():
    """获取短信验证码"""

    # 1、获取参数：用户输入的手机号、图片验证码、图片验证码的随机编码 （传入参数为Json格式）
    params_dict = request.json  # 可使用request.json方法直接获取
    mobile = params_dict.get('mobile')
    image_code = params_dict.get('image_code')
    image_code_id = params_dict.get('image_code_id')

    # 2、校验参数
    # 判断参数是否有值
    if not all([mobile, image_code, image_code_id]):
        # 返回错误类型为json格式 error errmsg
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 判断号码格式是否正确
    if not re.match(r"^1[3578][0-9]{9}", mobile):
        return jsonify(errno=RET.DATAERR, errmsg='数据错误')
    # 校验图片验证码是否一致
    # 从redis中读取
    try:
        real_image_code = redis_store.get('image_code_id_' + image_code_id)
    except Exception as a:
        current_app.logger.error(a)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
    if not real_image_code:
        # 验证码已过期
        return jsonify(errno=RET.NODATA, errmsg="验证码已过期")
    # 判断验证码是否一致
    # 若不一致，则返回错误
    if image_code.upper() != real_image_code.upper():
        return jsonify(errno=RET.DATAERR, errmsg='验证码错误')

    # 3、判断该号码是否注册过
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as a:
        current_app.logger.error(a)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
    # 若存在，返回手机号码已存在
    if user:
        return jsonify(errno=RET.DATAEXIST, errmsg='手机号码已存在')

    # 4、如果一致则生成短信验证码
    # 生成六位随机数
    str_num = "%06d" % random.randint(0, 999999)
    print(str_num)
    # result = CCP().send_template_sms(mobile, [str_num, constants.SMS_CODE_REDIS_EXPIRES/60], 1)
    # if result != 0: # 代表发送不成功
    #     return jsonify(errno=RET.THIRDERR, errmsg='第三方系统错误')
    # 如果发送成功将短信验证码存入redis中 并设置过期时间
    try:
        redis_store.set("sms_" + mobile, str_num, constants.SMS_CODE_REDIS_EXPIRES)
    except Exception as a:
        current_app.logger.error(a)
        return jsonify(errno=RET.DBERR, errmsg="保存短信验证码失败")
    return jsonify(errno=RET.OK, errmsg='发送成功')


@passport_blu.route('/register', methods=['POST'])
def register():
    """注册提交"""
    # 1、获取用户手机号码 短信验证码
    json_data = request.json
    mobile = json_data.get('mobile')
    sms_code = json_data.get('smscode')
    password = json_data.get('password')
    # 判断是否有值
    if not all([mobile, sms_code, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 2、从redis中获取短信验证码
    try:
        real_sms_code = redis_store.get("sms_" + mobile)
    except Exception as a:
        current_app.logger.error(a)
        return jsonify(errno=RET.DBERR, errmsg="获取本地验证码失败")
    if not real_sms_code:
        # 短信验证码过期
        return jsonify(errno=RET.NODATA, errmsg="短信验证码过期")
    if real_sms_code != sms_code:
        # 验证码输入是否正确
        return jsonify(errno=RET.DATAERR, errmsg='验证码错误')
    # 3、初始化user模型
    user = User()
    user.nick_name = mobile
    user.mobile = mobile

    # 对密码进行处理
    user.password = password

    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        # 数据保存错误
        return jsonify(errno=RET.DATAERR, errmsg="数据保存错误")
    # 4. 保存用户登录状态
    session["user_id"] = user.id
    session["nick_name"] = user.nick_name
    session["mobile"] = user.mobile

    # 5. 返回注册结果
    return jsonify(errno=RET.OK, errmsg="OK")


@passport_blu.route('/login', methods=['POST'])
def login():
    """用户登录"""
    # 1、获取参数
    param_dict = request.json
    mobile = param_dict.get('mobile')
    password = param_dict.get('password')

    # 2、校验参数
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 3、校验号码格式是否正确
    if not re.match(r"1[34578][0-9]{9}", mobile):
        return jsonify(errno=RET.DATAERR, errmsg='电话号码格式错误')

    # 4、校验号码是否存在 查询数据库
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as a:
        current_app.logger.error(a)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
    if not user:
        return jsonify(errno=RET.DATAERR, errmsg='号码不存在，请注册')

    # 5、校验密码是否正确
    if not user.check_passowrd(password):
        return jsonify(errno=RET.DATAERR, errmsg='用户名或密码错误')

    # 6、保存登录状态
    session["user_id"] = user.id
    session["nick_name"] = user.nick_name
    session["mobile"] = user.mobile
    # 保存用户最后一次登录时间
    # 在视图函数中若对模板中数据有所修改，需要commit提交
    # 若对sqlalchemy有所配置，每次修改后，可以不使用commit提交
    user.last_login = datetime.now()
    # try:
    #     db.session.commit()
    # except Exception as a:
    #     current_app.logger.error(a)
    #     db.session.rollback()
    # 7、返回响应
    return jsonify(errno=RET.OK, errmsg='登录成功')

@passport_blu.route('/logout')
def logout():
    """
    退出登录
    :return:
    """
    # 使用pop删除session中存储的登录信息
    session.pop('user_id')
    session.pop('nick_name')
    session.pop('mobile')
    session.pop('is_admin')
    # 返回成功的响应
    return jsonify(errno=RET.OK,errmssg='退出成功')
